#include <DataTypes/DataTypeDate.h>
#include <DataTypes/DataTypeDateTime.h>
#include <DataTypes/DataTypeDateTime64.h>
#include <DataTypes/DataTypeLowCardinality.h>
#include <DataTypes/DataTypeString.h>
#include <DataTypes/DataTypesNumber.h>
#include <Interpreters/AsynchronousMetricLog.h>
#include <Interpreters/AsynchronousMetrics.h>
#include <Common/time.h>


namespace DB
{

NamesAndTypesList AsynchronousMetricLogElement::getNamesAndTypes()
{
    return
    {
        {"event_date", std::make_shared<DataTypeDate>()},
        {"event_time", std::make_shared<DataTypeDateTime>()},
        {"event_time_microseconds", std::make_shared<DataTypeDateTime64>(6)},
        {"metric", std::make_shared<DataTypeLowCardinality>(std::make_shared<DataTypeString>())},
        {"value", std::make_shared<DataTypeFloat64>(),}
    };
}


void AsynchronousMetricLogElement::appendToBlock(MutableColumns & columns) const
{
    size_t column_idx = 0;

    columns[column_idx++]->insert(event_date);
    columns[column_idx++]->insert(event_time);
    columns[column_idx++]->insert(event_time_microseconds);
    columns[column_idx++]->insert(metric_name);
    columns[column_idx++]->insert(value);
}


void AsynchronousMetricLog::addValues(const AsynchronousMetricValues & values)
{
    AsynchronousMetricLogElement element;

    const auto now = std::chrono::system_clock::now();
    element.event_time = time_in_seconds(now);
    element.event_time_microseconds = time_in_microseconds(now);
    element.event_date = DateLUT::serverTimezoneInstance().toDayNum(element.event_time);

    for (const auto & [key, value] : values)
    {
        element.metric_name = key;
        element.value = value;

        add(element);
    }
}

}
